package com;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.ChannelGroupFuture;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import lombok.extern.slf4j.Slf4j;

/**
 * 处理HTTP请求
 */
@Slf4j
@SuppressWarnings("deprecation")
public class HttpRequestHandler extends SimpleChannelInboundHandler<HttpObject> {

    private static final File VIEW_STREAM = new File("static/view-stream.html");
    private static final File JSMPEG_MIN_JS = new File("static/jsmpeg.min.js");

    private final String wsUri;
    private String monitorIp;

    public HttpRequestHandler(String wsUri) {
        this.wsUri = wsUri;
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        if (msg instanceof HttpRequest) {
            HttpRequest request = (HttpRequest) msg;
            String uri = request.getUri();
            if (uri.contains("rtsp:/") && !uri.contains("rtsp://")) {
                uri = uri.replace("rtsp:/", "rtsp://");
            }
            log.info("收到HTTP请求：{}", uri);

            // 处理WebSocket请求
            if (uri.contains(wsUri)) {
                String ip = uri.split(wsUri + "/")[1];
                ChannelGroupHolder.add(ip, ctx.channel());
                TransferRtspHelper.open(ip);
                ctx.fireChannelRead(new DefaultFullHttpRequest(request.protocolVersion(), request.method(), wsUri,
                        Unpooled.buffer(), request.headers(), request.headers()));
            } else if (uri.contains("/push/")) {
                monitorIp = uri.split("/push/")[1];
                log.info("开始接收转码推流：{}", monitorIp);
            }
            // 处理HTTP请求
            else {
                FullHttpResponse response = null;
                if ("/".equals(uri)) {
                    response = generateResponse(request, new RandomAccessFile(VIEW_STREAM, "r"));
                    response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/html;charset=UTF-8");
                } else if ("/jsmpeg.min.js".equals(uri)) {
                    response = generateResponse(request, new RandomAccessFile(JSMPEG_MIN_JS, "r"));
                    response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "application/x-javascript");
                } else {
                    response = generateResponse(request, null);
                }
                ctx.write(response);
                ChannelFuture future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
                if (!HttpHeaders.isKeepAlive(request)) {
                    future.addListener(ChannelFutureListener.CLOSE);
                }
            }
        } else if (msg instanceof HttpContent && !(msg instanceof LastHttpContent)) {
            HttpContent chunk = (HttpContent) msg;
            ChannelGroup group = ChannelGroupHolder.get(monitorIp);
            ChannelGroupFuture groupFuture = group.writeAndFlush(new BinaryWebSocketFrame(chunk.retain().content()));
            groupFuture.sync();
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

    /**
     * 生成HTTP响应
     */
    private FullHttpResponse generateResponse(HttpRequest request, RandomAccessFile file) throws IOException {
        ByteBuf buf = generateByteBuf(file);
        FullHttpResponse response = new DefaultFullHttpResponse(request.getProtocolVersion(), HttpResponseStatus.OK,
                buf);
        if (HttpHeaders.isKeepAlive(request)) {
            response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
        }
        response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, buf.writerIndex());
        return response;
    }

    /**
     * 生成HTTP响应内容
     */
    private ByteBuf generateByteBuf(RandomAccessFile file) throws IOException {
        ByteBuf buf = Unpooled.buffer(0);
        if (file != null) {
            int length = (int) file.length();
            byte[] fileByte = new byte[length];
            file.read(fileByte);
            file.close();

            buf = Unpooled.buffer(length);
            for (int i = 0; i < length; i++) {
                buf.writeByte(fileByte[i]);
            }
        }
        return buf;
    }

}
